﻿using Renci.SshNet;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CommonLibrary.Utils
{

    /// <summary>
    /// SFTP上传文件
    /// SSH.NET.dll
    /// </summary>
    public class CommonSFTP : IDisposable
    {
        //private SshClient SSH;
        private SftpClient SFtp;
        private ConnectionInfo ConnInfo;

        public string Host { get; private set; }
        public int Port { get; private set; }
        public string User { get; private set; }
        public string Passwd { get; private set; }

        public CommonSFTP(string host, int port, string user, string passwd)
        {
            Host = host;
            Port = port;
            User = user;
            Passwd = passwd;

            ConnInfo = new ConnectionInfo(Host, Port, User, new PasswordAuthenticationMethod(User, Passwd));
            ConnInfo.Timeout = TimeSpan.FromMilliseconds(int.MaxValue);
            //SSH = new SshClient(ConnInfo);
            SFtp = new SftpClient(ConnInfo);
            //KeepAliveTimer = new Timer();
            //KeepAliveTimer.Enabled = true;
            //KeepAliveTimer.Elapsed += ClientKeepAlive;
            //KeepAliveTimer.Interval = int.MaxValue - ushort.MaxValue;
        }

        public void Connect()
        {
            //SSH.Connect();
            SFtp.Connect();
        }

        /// <summary>
        /// Sftp上穿文件
        /// </summary>
        /// <param name="localFile"></param>
        /// <param name="localBasePath"></param>
        /// <param name="linuxRootPath"></param>
        /// <param name="onlyFile"></param>
        public void UploadFile(string localFile, string localBasePath, string linuxRootPath)
        {
            string fileName = Path.GetFileName(localFile);

            localBasePath = localBasePath.Replace("\\", "/");
            localFile = localFile.Replace("\\", "/");

            string relativePath = localFile.Replace(localBasePath, string.Empty);
            if (relativePath.StartsWith("/"))
                relativePath = relativePath.Substring(1);

            string relativeFolder = relativePath.Replace(fileName, string.Empty);
            string linuxSaveFolder = Path.Combine(linuxRootPath, relativeFolder).Replace("\\", "/");
            string linuxPath = Path.Combine(linuxRootPath, relativePath).Replace("\\", "/");
            string lp = linuxPath.Replace(fileName, string.Empty);

            CreateRemoteFolder(lp);
            using var stream = File.OpenRead(localFile);
            SFtp.BufferSize = 1024 * 1024 * 8;
            SFtp.UploadFile(stream, linuxPath, true);
        }

        ///// <summary>
        ///// 设置文件夹权限
        ///// </summary>
        ///// <param name="fullFolder"></param>
        ///// <param name="baseFolder"></param>
        //public string SetPermissions(string fullFolder, string permissions = "rw")
        //{
        //    var cmd = SSH.CreateCommand($"chmod +{permissions} {fullFolder}");
        //    return cmd.Execute();
        //}

        ///// <summary>
        ///// 创建单个目录
        ///// </summary>
        ///// <param name="folder"></param>
        ///// <returns></returns>
        //public string CreateRemoteFolder(string folder)
        //{
        //    var cmd = SSH.CreateCommand($"mkdir -p {folder}");
        //    return cmd.Execute();
        //}

        public void CreateRemoteFolder(string folder)
        {
            string[] parrs = folder.Split("/").Where(s => !string.IsNullOrEmpty(s)).ToArray();
            int len = parrs.Length;
            if (len == 0)
                return;

            string curPath = string.Empty;
            for (int i = 0; i < len; i++)
            {
                curPath = $"{curPath}/{parrs[i]}";
                if (!SFtp.Exists(curPath))
                    SFtp.CreateDirectory(curPath);
            }

        }

        private List<string> GetAllDirectory(string folder)
        {
            List<string> retArr = new List<string>(20);

            var list = SFtp.ListDirectory(folder);
            var dirs = list.Where(s => s.Attributes.IsDirectory).Select(s => s.FullName)
                .Where(s => !s.EndsWith("/.") && !s.EndsWith("/..")).ToArray();

            if (dirs.Length == 0)
                return retArr;

            retArr.AddRange(dirs);
            foreach (string item in dirs)
                retArr.AddRange(GetAllDirectory(item));

            return retArr;
        }

        ///// <summary>
        ///// 客户端保活
        ///// </summary>
        ///// <param name="sender"></param>
        ///// <param name="e"></param>
        //private void ClientKeepAlive(object sender, ElapsedEventArgs e)
        //{
        //    var cmd = SSH.CreateCommand($"cd ./");
        //    _ = cmd.Execute();
        //}

        #region
        private bool disposedValue;

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    // TODO: 释放托管状态(托管对象)
                    //KeepAliveTimer.Stop();
                    //if (SSH.IsConnected)
                    //    SSH.Disconnect();
                    if (SFtp.IsConnected)
                        SFtp.Disconnect();
                    //SSH.Dispose();
                    SFtp.Dispose();
                    //KeepAliveTimer.Dispose();
                }
                //SSH = null;
                SFtp = null;
                //KeepAliveTimer = null;
                disposedValue = true;
            }
        }

        public void Dispose()
        {
            // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
            Dispose(disposing: true);
            GC.SuppressFinalize(this);
        }
        #endregion

    }
}